package sk.stancel.peter.sudoku.activities;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import sk.stancel.peter.sudoku.R;
import sk.stancel.peter.sudoku.Sudoku;
import sk.stancel.peter.sudoku.TileAdapter;
import sk.stancel.peter.sudoku.core.Field;
import sk.stancel.peter.sudoku.core.GameState;
import sk.stancel.peter.sudoku.core.Hint;
import sk.stancel.peter.sudoku.core.Tile;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.google.ads.AdRequest;
import com.google.ads.AdView;

public class SudokuActivity extends Activity implements OnItemClickListener, OnCheckedChangeListener, OnItemLongClickListener{

	private GridView gridView;
	private int number = 1;
	private Field field;
	private Vibrator vibration;
	private WakeLock wakeLock;
	private TileAdapter adapter;
	private Sudoku sudoku;
	private boolean isHard;
	private boolean isMedium;
	private AdView adView;
	private SharedPreferences prefs;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sudoku);

        adView = (AdView) this.findViewById(R.id.adViewSudoku);
        adView.loadAd(new AdRequest());

        vibration = (Vibrator) getSystemService(VIBRATOR_SERVICE);

		gridView = (GridView) findViewById(R.id.gridview);

		sudoku = (Sudoku) getApplication();

		isHard = getIntent().getBooleanExtra("hard_type", false);
		isMedium = getIntent().getBooleanExtra("medium_type", false);
		int[] ints = getIntent().getIntArrayExtra("int_array");
		
		prefs = this.getSharedPreferences("preferences", Context.MODE_PRIVATE);
		prefs.edit().putInt("sudoku_preferences_font_size", prefs.getInt("sudoku_preferences_font_size", Integer.valueOf(obtainStyledAttributes(R.style.tile_text, new int[] {android.R.attr.textSize}).getString(0).split("\\.")[0]))).commit();
		prefs.edit().putInt("sudoku_preferences_font_size_hint", prefs.getInt("sudoku_preferences_font_size_hint", Integer.valueOf(obtainStyledAttributes(R.style.text_hint, new int[] {android.R.attr.textSize}).getString(0).split("\\.")[0]))).commit();
		
		Field field = null;
		if(savedInstanceState != null){
			field = (Field) savedInstanceState.getSerializable("actual_game");
			sudoku.setEasyMode(savedInstanceState.getBoolean("easy_mode", true));
			isHard = savedInstanceState.getBoolean("hard_type", false);
			isMedium = savedInstanceState.getBoolean("medium_type", false);
		}

		if(field == null){
			if(ints == null){
				if(isMedium){
					this.field = sudoku.newGame();
				}else {
					File file = new File(getIntent().getStringExtra("file_path"));
					this.field = sudoku.loadSudoku(file);
				}
			}else {
				if(isHard){
					sudoku.setEasyMode(false);
				}
				this.field = sudoku.customNewGame(ints, isHard);
			}
		}else{
			this.field = sudoku.loadNewGame(field, isHard);
			if(isHard){
				sudoku.setEasyMode(false);
			}
		}

		List<Tile> tiles = new ArrayList<Tile>();

		for (int row = 0; row < 9; row++) {
            for (int column = 0; column < 9; column++) {
                tiles.add(this.field.getPlayTile(row, column));
            }
		}
 
		adapter = new TileAdapter(this, tiles);
		gridView.setAdapter(adapter);
		gridView.setOnItemLongClickListener(this);
		gridView.setOnItemClickListener(this);
		((RadioGroup) findViewById(R.id.toggleGroup)).setOnCheckedChangeListener(this);

		PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Sudoku");
        wakeLock.acquire();
    }

	public boolean onItemLongClick(AdapterView<?> parent, View v, int position, long id) {
		TextView tv = (TextView) v.findViewById(R.id.text_tile);

		if(field.getState().equals(GameState.PLAYING) && tv.getCurrentTextColor() != Color.RED){
			LinearLayout ll = (LinearLayout) v.findViewById(R.id.layout_hints);
			if(ll.getVisibility() == View.VISIBLE){
				ll.setVisibility(View.GONE);
				tv.setVisibility(View.VISIBLE);
			}
			int row = position / 9;
			int column = position % 9;
			int num = number;
			if(tv.getText().equals(number+"")){
				ll.setVisibility(View.VISIBLE);
				tv.setVisibility(View.GONE);
				num = 0;
				tv.setText("");
			}else tv.setText(number+"");

			field.setPlayTile(row, column, num);
			v.setBackgroundResource(Sudoku.getBackgroundImageID(position, num));
			if (field.getState().equals(GameState.SOLVED)) {
	            Toast.makeText(this, R.string.congratulations, Toast.LENGTH_LONG).show();
	            if(wakeLock.isHeld()){
		            wakeLock.release();
	            }
	        }
		}
		vibration.vibrate(50);
		return true;
	}

	public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
		TextView tv = (TextView) v.findViewById(R.id.text_tile);
		if(tv.getVisibility() != View.VISIBLE){
			switch (number) {
			case 1:
				tv = (TextView) v.findViewById(R.id.text_hint1);
				break;
			case 2:
				tv = (TextView) v.findViewById(R.id.text_hint2);
				break;
			case 3:
				tv = (TextView) v.findViewById(R.id.text_hint3);
				break;
			case 4:
				tv = (TextView) v.findViewById(R.id.text_hint4);
				break;
			case 5:
				tv = (TextView) v.findViewById(R.id.text_hint5);
				break;
			case 6:
				tv = (TextView) v.findViewById(R.id.text_hint6);
				break;
			case 7:
				tv = (TextView) v.findViewById(R.id.text_hint7);
				break;
			case 8:
				tv = (TextView) v.findViewById(R.id.text_hint8);
				break;
			case 9:
				tv = (TextView) v.findViewById(R.id.text_hint9);
				break;
			}
			Tile tile = (Tile) parent.getItemAtPosition(position);
			if(tv.getVisibility() != View.VISIBLE){
				tv.setVisibility(View.VISIBLE);
				tile.getHints()[number-1].setShow(true);
			}else {
				tv.setVisibility(View.INVISIBLE);
				tile.getHints()[number-1].setShow(false);
			}
		}
	}

	public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
		for (int j = 0; j < radioGroup.getChildCount(); j++) {
            final ToggleButton view = (ToggleButton) radioGroup.getChildAt(j);
            view.setChecked(view.getId() == checkedId);
        }
	}

	public void onToggle(View view) {
	    ((RadioGroup)view.getParent()).check(view.getId());

	    ToggleButton tb = (ToggleButton) view;
	    number = Integer.valueOf(tb.getTextOn().toString());
	    tb.setChecked(true);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.option_menu, menu);
		if(isHard){
			menu.getItem(2).setVisible(false);
			menu.getItem(0).setVisible(false);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);

		switch (item.getItemId()) {
			case (R.id.easy_mode): {
				if(sudoku.isEasyMode()){
					sudoku.setEasyMode(false);
				}else {
					sudoku.setEasyMode(true);
				}
				adapter.notifyDataSetChanged();
				return true;
			}
			case (R.id.restart_sudoku): {
				for (int row = 0; row < 9; row++) {
		            for (int column = 0; column < 9; column++) {
		            	Tile tile = field.getPlayTile(row, column);
		                if (tile.isChange()) {
		                    tile.setValue(0);
		                    for(Hint hint : tile.getHints()){
		                    	hint.setShow(false);
		                    }
		                }
		            }
		        }
		        field.setState(GameState.PLAYING);
		        adapter.notifyDataSetChanged();
				return true;
			}
			case (R.id.solve_sudoku): {
				if(isMedium){
					field.solveMedium();
					adapter.notifyDataSetChanged();
		            Toast.makeText(this, R.string.congratulations, Toast.LENGTH_LONG).show();
				}else if(!isHard){
					while(sudoku.getSudokuCheck().getString().startsWith("Checking")){
			            try {
			                synchronized(this){
			                    this.wait(2000);
			                }
			            } catch (InterruptedException ex) {
			                System.out.println("ERROR: "+ex.getMessage());
			            }
			        }
					if (field.solveIt()) {
			            field.setState(GameState.SOLVED);
			            adapter.notifyDataSetChanged();
			            Toast.makeText(this, R.string.congratulations, Toast.LENGTH_LONG).show();
			        } else {
			        	Toast.makeText(this, R.string.no_solution, Toast.LENGTH_LONG).show();
			        }
				}
				return true;
			}
			case (R.id.save_sudoku): {
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setTitle(R.string.set_file_name);
				final EditText editText = new EditText(this);
				final Context context = this;
				builder.setView(editText);
				builder.setPositiveButton(R.string.save, new OnClickListener() {

					public void onClick(DialogInterface dialog, int which) {
						final String text = editText.getText().toString().trim();
						if(text.length() != 0 && !text.contains(".")){
							if(!sudoku.saveSudoku(text, false)){
								AlertDialog.Builder warning = new AlertDialog.Builder(context);
								warning.setTitle(R.string.warning);
								warning.setMessage(R.string.name_exist);
								warning.setPositiveButton(R.string.yes, new OnClickListener() {
									public void onClick(DialogInterface dialog, int which) {
										sudoku.saveSudoku(text, true);
									}
								});
								warning.setNegativeButton(R.string.no, new OnClickListener() {
									public void onClick(DialogInterface dialog, int which) {
										dialog.cancel();
									}
								});
								AlertDialog alertt = warning.create();
								alertt.show();
							}
						}
					}
				});
				AlertDialog alert = builder.create();
				alert.show();
			}
			case (R.id.set_font): {
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setTitle(R.string.set_font);
				LinearLayout ll = (LinearLayout) getLayoutInflater().inflate(R.layout.seekbar, null);
				
				SeekBar seekBar = (SeekBar) ll.findViewById(R.id.seekbar);
				SeekBar seekBarHint = (SeekBar) ll.findViewById(R.id.seekbar_hint);
				final TextView tw = (TextView) ll.findViewById(R.id.text_seekbar);
				final TextView twHint = (TextView) ll.findViewById(R.id.text_seekbar_hint);
				tw.setText(prefs.getInt("sudoku_preferences_font_size", 1) + "");
				seekBar.setProgress(prefs.getInt("sudoku_preferences_font_size", 1));
				twHint.setText(prefs.getInt("sudoku_preferences_font_size_hint", 1) + "");
				seekBarHint.setProgress(prefs.getInt("sudoku_preferences_font_size_hint", 1));
				seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
					@Override
					public void onStopTrackingTouch(SeekBar seekBar) {
					}
					
					@Override
					public void onStartTrackingTouch(SeekBar seekBar) {
					}
					
					@Override
					public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
						tw.setText(progress + "");
						prefs.edit().putInt("sudoku_preferences_font_size", progress).commit();
						adapter.notifyDataSetChanged();
					}
				});
				seekBarHint.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
					@Override
					public void onStopTrackingTouch(SeekBar seekBar) {
					}
					
					@Override
					public void onStartTrackingTouch(SeekBar seekBar) {
					}
					
					@Override
					public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
						twHint.setText(progress + "");
						prefs.edit().putInt("sudoku_preferences_font_size_hint", progress).commit();
						adapter.notifyDataSetChanged();
					}
				});
				builder.setView(ll);
				builder.setPositiveButton(R.string.set, new OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
//						prefs.edit().putInt("sudoku_preferences_font_size", Integer.valueOf(tw.getText().toString())).commit();
//						prefs.edit().putInt("sudoku_preferences_font_size_hint", Integer.valueOf(twHint.getText().toString())).commit();
//						adapter.notifyDataSetChanged();
					}
				});
				AlertDialog alert = builder.create();
				alert.show();
			}
		}
		return false;
	}

	@Override
	public void onBackPressed() {
		if(wakeLock.isHeld()){
            wakeLock.release();
        }
		super.onBackPressed();
	}

	@Override
	protected void onDestroy() {
		if (adView != null) {
			adView.destroy();
		}
		if(wakeLock.isHeld()){
            wakeLock.release();
        }
		super.onDestroy();
	}

	@Override
	protected void onPause() {
		if(wakeLock.isHeld()){
            wakeLock.release();
        }
		super.onPause();
	}

	@Override
	protected void onResume() {
		wakeLock.acquire();
		super.onResume();
	}

	@Override
	protected void onStop() {
		if(wakeLock.isHeld()){
            wakeLock.release();
        }
		super.onStop();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		outState.putSerializable("actual_game", field);
		outState.putBoolean("hard_type", isHard);
		outState.putBoolean("medium_type", isMedium);
		outState.putBoolean("easy_mode", sudoku.isEasyMode());
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		onCreate(savedInstanceState);
	}
}